package cn.ording.dao.imp;

import java.io.Serializable;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import cn.ording.dao.BaseDao;
import cn.ording.util.Page;
import cn.ording.util.QueryFactory;

public class BaseDaoHibernateImp<T> implements BaseDao<T> {
	protected static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};
	protected HibernateTemplate hibernateTemplate;
	private final Class<T> clazz;
	private String defaultOrder = " order by obj.id";

	public BaseDaoHibernateImp(Class<T> clazz) {
		this.clazz =clazz;   
	}
	
	
	/**
	 * 查询-根据主键ID查询
	 * 
	 * @param id
	 * @return
	 */
	public T query(Serializable id) {
		T t = (T) this.hibernateTemplate.get(clazz, id);
		if (t == null)
			throw new DataRetrievalFailureException("Object not found.");
		return t;
	}

	/**
	 * 创建
	 * 
	 * @param t
	 */
	public void create(T t) {
		this.hibernateTemplate.save(t);
	}

	/**
	 * 删除
	 * 
	 * @param t
	 */
	public void delete(T t)throws Exception {
		this.hibernateTemplate.delete(t);
	}

	/**
	 * 更新
	 * 
	 * @param t
	 */
	public void update(T t) {
		this.hibernateTemplate.update(t);
	}

	/**
	 * 根据指定主键ID删除对象
	 * 
	 * @param id
	 *            主键ID
	 */
	public void delete(Serializable id) {
		T t = (T) this.hibernateTemplate.get(clazz, id);
		this.hibernateTemplate.delete(t);
		if (t == null)
			throw new DataRetrievalFailureException("Object not found.");
	}

	/**
	 * 查询全部
	 * 
	 * @return
	 */
	public List<T> query(String queryMethod) {
		String pClassName = clazz.getSimpleName();
		String select = "from " +pClassName+" as obj" 
		+ defaultOrder;
		return query(select,queryMethod);
	}

	/**
	 * 查询全部
	 * 
	 * @return
	 */
	public List<T> queryByOrder(String order,String queryMethod) {
		if (null == order || order.equals("")) {
			order = defaultOrder;
		} else {
			order = " order by obj." + order;
		}
		String select = "select obj from " + clazz.getName() + " as obj "
				+ order;
		return query(select,queryMethod);
	}

	/**
	 * 查询对象
	 * 
	 * @param select
	 *            sql查询语句
	 * @return
	 */
	public List query(final String select,final String queryMethod) {
		return query(select, EMPTY_OBJECT_ARRAY,queryMethod);
	}

	/**
	 * 根据条件查询
	 * 
	 * @param select
	 *            hql查询语句
	 * @param values
	 *            Object[]类型的参数对象
	 * @return 返回List类型查询结果
	 */
	public List query(final String select, final Object[] values ,final String queryMethod) {
		return (List)this.hibernateTemplate.execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = QueryFactory.getQuery(session,select,queryMethod);
				if (values != null) {
					for (int i = 0; i < values.length; i++)
						query.setParameter(i, values[i]);
				}
				return query.list();
			}
		});
	}
	/**
	 * 使用SQL语句查询
	 * @param select
	 *            sql查询语句
	 * @param values
	 *            Object[]类型的参数对象
	 * @return 返回List类型查询结果
	 */
	public List<T> queryBySql(final String select , final Object[] objects ,String queryMethod){
		return (List)hibernateTemplate.execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createSQLQuery(select);
				if (objects != null) {
					for (int i = 0; i < objects.length; i++)
						query.setParameter(i, objects[i]);
				}
				return query.list();
			}
		});
	}
	/**
	 * 全部数据分页查询
	 * @param page  Page实例对象
	 * @return 返回List<T>类型查询结果
	 */
	public List<T> query(Page page,String queryMethod) {
		String selectCount = "select count(*) from " + clazz.getName() + " as obj where 1=1";
		String select = "select obj from " + clazz.getName() + " as obj";
		return queryForList(selectCount, select,EMPTY_OBJECT_ARRAY,EMPTY_OBJECT_ARRAY, page,queryMethod);
	}
	
	/**
	 * 条件分页查询
	 * @param page Page实例对象
	 * @param conditions 条件数组
	 * @param values 条件值
	 * @return
	 */
	public List<T> query(Page page, final Object[] conditions, final Object[] values,final String queryMethod) {
		String selectCount = "select count(*) from " + clazz.getName() + " as obj where 1=1";
		String select = "select obj from " + clazz.getName() + " as obj";
		return queryForList(selectCount, select,conditions, values, page,queryMethod);
	}
	
	/**
	 * 分页查询辅助方法
	 * @param selectCount  查询总数的SQL语句
	 * @param select  查询SQL语句
	 * @param values  Object[]类型的参数对象
	 * @param page  Page实例对象
	 * @return 
	 */
	public List queryForList(final String selectCount, final String select, final Object[] conditions,final Object[] values, final Page page,final String queryMethod) {
		Object object = queryForObject(selectCount, conditions,values,queryMethod);
		Long count = null;
		if(object instanceof BigInteger){
			count = ((BigInteger)object).longValue();
		}else{
			count = (Long) object;
		}
		page.setTotalCount(count.intValue());
		if (page.isEmpty())
			return Collections.EMPTY_LIST;
		return queryForList(select, conditions,values, page,queryMethod);
	}
	
	public List queryForListSql(final String selectCount, final String select, final Object[] conditions,final Object[] values, final Page page,final String queryMethod,Class<T> targetClass) {
		Object object = queryForObject(selectCount, conditions,values,queryMethod);
		Long count = null;
		if(object instanceof BigInteger){
			count = ((BigInteger)object).longValue();
		}else{
			count = (Long) object;
		}
		page.setTotalCount(count.intValue());
		if (page.isEmpty())
			return Collections.EMPTY_LIST;
		return queryForList(select, conditions,values, page,queryMethod,targetClass);
	}

    /**
     * 分页查询
     * @param select sql查询语句
     * @param values Object[]类型的参数对象
     * @param page Page实例对象
     * @return
     */
	public List queryForList(final String select, final Object[] conditions,final Object[] values, final Page page,final String queryMethod) {
		HibernateCallback selectCallback = new HibernateCallback() {
			public Object doInHibernate(Session session) {
				StringBuffer condition_buffer=new StringBuffer();
				condition_buffer.append(select);
				if(conditions!=null){
					for(int i=0;i<conditions.length;i++){
						condition_buffer.append(" and ");
						condition_buffer.append(conditions[i]);
						condition_buffer.append("=? ");
					}		
				}
				Query query = QueryFactory.getQuery(session,condition_buffer.toString(),queryMethod);
				if (values != null) {
					for (int i = 0; i < values.length; i++)
						query.setParameter(i, values[i]);
				}
				return query.setFirstResult(page.getFirstResult()).setMaxResults(page.getPageSize()).list();
			}
		};
		return (List) hibernateTemplate.executeFind(selectCallback);
	}
	
	public List queryForList(final String select, final Object[] conditions,final Object[] values, final Page page,final String queryMethod ,final Class<T> targetClass) {
		HibernateCallback selectCallback = new HibernateCallback() {
			public Object doInHibernate(Session session) {
				StringBuffer condition_buffer=new StringBuffer();
				condition_buffer.append(select);
				if(conditions!=null){
					for(int i=0;i<conditions.length;i++){
						condition_buffer.append(" and ");
						condition_buffer.append(conditions[i]);
						condition_buffer.append("=? ");
					}		
				}
				Query query = QueryFactory.getQuery(session,condition_buffer.toString(),queryMethod);
				((SQLQuery)query).addEntity(targetClass);
				if (values != null) {
					for (int i = 0; i < values.length; i++)
						query.setParameter(i, values[i]);
				}
				return query.setFirstResult(page.getFirstResult()).setMaxResults(page.getPageSize()).list();
			}
		};
		return (List) hibernateTemplate.executeFind(selectCallback);
	}

	/**
	 * 根据制定条件查询对象-分页条件查询
	 * @param select sql查询语句
	 * @param values Object[]类型的参数对象
	 * @return
	 */
	protected Object queryForObject(final String select, final Object[] conditions,final Object[] values,final String queryMethod) {
		HibernateCallback selectCallback = new HibernateCallback() {
			public Object doInHibernate(Session session) {
				StringBuffer condition_buffer=new StringBuffer();
				condition_buffer.append(select);
				if(conditions!=null){
					for(int i=0;i<conditions.length;i++){
						condition_buffer.append(" and ");
						condition_buffer.append(conditions[i]);
						condition_buffer.append("=? ");
					}		
				}
				Query query = QueryFactory.getQuery(session,condition_buffer.toString(),queryMethod);
				if (values != null) {
					for (int i = 0; i < values.length; i++)
						query.setParameter(i, values[i]);
				}
				return query.uniqueResult();
			}
		};
		return hibernateTemplate.execute(selectCallback);
	}
	
	/**
	 * 根据制定条件查询对象
	 * @param select sql查询语句
	 * @param values Object[]类型的参数对象
	 * @return
	 */
    public Object queryForObject(final String select, final Object[] values ,final String queryMethod) {
        HibernateCallback selectCallback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                Query query = QueryFactory.getQuery(session,select,queryMethod);
                if(values!=null) {
                    for(int i=0; i<values.length; i++)
                        query.setParameter(i, values[i]);
                }
                return query.uniqueResult();
            }
        };
        return hibernateTemplate.execute(selectCallback);
    }
    
    
    //======================== pagenation
    
	public List queryForPage(final String selectCount, final String select, final Object[] values, final Page page,final String queryMethod) {
		Long count = (Long) queryForObject(selectCount, values ,queryMethod);
		page.setTotalCount(count.intValue());
		if (page.isEmpty())
			return Collections.EMPTY_LIST;
		return queryForList(select, values, page,queryMethod);
	}
	

	@SuppressWarnings("unchecked")
	public List queryForList(final String select,final Object[] values, final Page page,final String queryMethod) {
		HibernateCallback selectCallback = new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = QueryFactory.getQuery(session,select,queryMethod);
				if (values != null) {
					for (int i = 0; i < values.length; i++)
						query.setParameter(i, values[i]);
				}
				return query.setFirstResult(page.getFirstResult()).setMaxResults(page.getPageSize()).list();
			}
		};
		return (List) hibernateTemplate.executeFind(selectCallback);
	}

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}
	@Resource(name="hibernateTemplate")
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}


	@SuppressWarnings("unchecked")
	public List<T> queryBySql(final String select, final Object[] objects,
			String queryMethod, final Class entity) {
		return (List)hibernateTemplate.execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createSQLQuery(select).addEntity(entity);
				if (objects != null) {
					for (int i = 0; i < objects.length; i++)
						query.setParameter(i, objects[i]);
				}
				return query.list();
			}
		});
	}
}
